package org.graniteds.example.gae.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.FetchPlan;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import org.granite.tide.annotations.TideEnabled;
import org.graniteds.example.gae.entities.Task;
import org.graniteds.example.gae.entities.TaskHistory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.annotation.Secured;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.google.appengine.api.datastore.Key;


@Controller("taskController")
@Transactional
@TideEnabled
public class TaskController {

	private PersistenceManagerFactory pmf;
	
	@Autowired
	public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
		this.pmf = pmf;
	}
    
	
	@SuppressWarnings("unchecked")
    @RequestMapping("/task/list")
    public ModelMap listTasks() {
    	PersistenceManager pm = pmf.getPersistenceManager();
    	try {
    		pm.getFetchPlan().setDetachmentOptions(FetchPlan.DETACH_UNLOAD_FIELDS);
    		List<Task> taskList = null;
    		Query q = pm.newQuery(Task.class);
    		try {
	    		taskList = (List<Task>)q.execute();
    		}
    		finally {
    			q.closeAll();
    		}
    		return new ModelMap("taskList", pm.detachCopyAll(taskList));
    	}
    	finally {
    		pm.close();
    	}
    }
    
    @RequestMapping("/task/create")
    @Secured({"ROLE_ADMIN"})
    public ModelMap createTask(@RequestParam("task") Task task) {
    	PersistenceManager pm = pmf.getPersistenceManager();
    	try {
    		task.setAssignedTo(null);
    		task.setStatus(Task.TaskStatus.CREATED);
    		TaskHistory taskHistory = new TaskHistory();
    		taskHistory.setTask(task);
    		taskHistory.setDescription("Task created by " + SecurityContextHolder.getContext().getAuthentication().getName());
    		if (task.getHistory() == null)
    			task.setHistory(new ArrayList<TaskHistory>());
    		task.getHistory().add(taskHistory);
    		pm.makePersistent(task);
    		pm.flush();
    		return new ModelMap("task", pm.detachCopy(task));
    	}
    	finally {
    		pm.close();
    	}
    }
    
    @RequestMapping("/task/remove")
    @Secured({"ROLE_ADMIN"})
    public ModelMap deleteTask(@RequestParam("taskId") Key taskId) {
    	PersistenceManager pm = pmf.getPersistenceManager();
    	try {
    		Task task = (Task)pm.getObjectById(Task.class, taskId);
    		pm.deletePersistent(task);
    		pm.flush();
    		return new ModelMap("task", task);
    	}
    	finally {
    		pm.close();
    	}
    }
    
    @RequestMapping("/task/assign")
    @Secured({"ROLE_USER"})
    public ModelMap assignTaskToCurrentUser(@RequestParam("taskId") Key taskId) {
    	PersistenceManager pm = pmf.getPersistenceManager();
    	try {
    		Task task = (Task)pm.getObjectById(Task.class, taskId);
    		task.setAssignedTo(SecurityContextHolder.getContext().getAuthentication().getName());
    		task.setStatus(Task.TaskStatus.ASSIGNED);
    		TaskHistory taskHistory = new TaskHistory();
    		taskHistory.setTask(task);
    		taskHistory.setDescription("Task assigned to " + task.getAssignedTo());
    		if (task.getHistory() == null)
    			task.setHistory(new ArrayList<TaskHistory>());
    		task.getHistory().add(taskHistory);
    		pm.flush();
    		return new ModelMap("task", pm.detachCopy(task));
    	}
    	finally {
    		pm.close();
    	}
    }
    
    @RequestMapping("/task/finish")
    @Secured({"ROLE_USER"})
    public ModelMap finishTask(@RequestParam("taskId") Key taskId) {
    	PersistenceManager pm = pmf.getPersistenceManager();
    	try {
    		Task task = (Task)pm.getObjectById(Task.class, taskId);
    		task.setStatus(Task.TaskStatus.FINISHED);       
    		TaskHistory taskHistory = new TaskHistory();
    		taskHistory.setTask(task);
    		taskHistory.setDescription("Task finished by " + SecurityContextHolder.getContext().getAuthentication().getName());
    		if (task.getHistory() == null)
    			task.setHistory(new ArrayList<TaskHistory>());
    		task.getHistory().add(taskHistory);
	       	pm.flush();
	       	return new ModelMap("task", pm.detachCopy(task));
    	}
    	finally {
    		pm.close();
    	}
    }
}
